
#include <FreeTDS/sybfront.h>
#include <FreeTDS/sybdb.h>
#include "wm_MSSql.h"
#include "wm_MSSqlResult.h"

#define MSSQL_CHARACTER_UTF8    "UTF-8"

namespace worm
{

wmMSSql::wmMSSql()
{
    m_pMsSql = NULL;
}

wmMSSql::~wmMSSql()
{
    Close();
}

bool wmMSSql::Open(const char* pStrInfo)
{
    if (!Initialize(pStrInfo))
    {
        return false;
    }

    dbinit();
    LOGINREC *pLoginRec = dblogin();
    DBSETLUSER(pLoginRec, m_szUser);
    DBSETLPWD(pLoginRec, m_szPassword);
    DBSETLCHARSET(pLoginRec, MSSQL_CHARACTER_UTF8);

    m_pMsSql = dbopen(pLoginRec, m_szIP);
    if (FAIL == m_pMsSql)
    {
        //std::cout << "Connect to SQL Server failed!" << std::endl;
        return false;
    }

    if (dbuse((DBPROCESS*)m_pMsSql, m_szDBName) == FAIL)
    {
        Close();
        //std::cout << "Use table failed!" << std::endl;
        return false;
    }

    if (m_bAsync)
    {
        RakNet::RakThread::Create(&wmDatabase::AsyncRun, this);
    }

    return true;
}

void wmMSSql::Close(void)
{
    if (NULL != m_pMsSql)
    {
        dbclose((DBPROCESS*)m_pMsSql);
    }

    m_bStop = true;

    m_oStopSem.WaitSemaphore();
}

bool wmMSSql::DirectExecute(const char* pStrSql)
{
    assert(NULL != pStrSql);
    if (NULL == m_pMsSql)
    {
        return false;
    }

    m_oSqlLock.Lock();
    dbcmd((DBPROCESS*)m_pMsSql, pStrSql);    
    if (dbsqlexec((DBPROCESS*)m_pMsSql) == FAIL)
    {
        //std::cout << "Query from database failed!" << std::endl;
        return false;
    }
    m_oSqlLock.Unlock();

    return true;
}

bool wmMSSql::DirectExecute(CSqlTaskSet* const pTaskSet)
{
    if (NULL == m_pMsSql)
    {
        return false;
    }

    std::vector<ISqlTask*>& aTaskList = *(pTaskSet->TaskList());

    m_oSqlLock.Lock();
    if (pTaskSet->IsTransaction())
    {
        BeginTransaction();
        for (uint32 i=0; i<aTaskList.size(); ++i)
        {
            dbcmd((DBPROCESS*)m_pMsSql, aTaskList[i]->sql());    
            if (dbsqlexec((DBPROCESS*)m_pMsSql) == FAIL)
            {
                //std::cout << "Query from database failed!" << std::endl;
                RollbackTransaction();
                m_oSqlLock.Unlock();
                return false;
            }
        }
        CommitTransaction();
    }
    else
    {
        for (uint32 i=0; i<aTaskList.size(); ++i)
        {
            dbcmd((DBPROCESS*)m_pMsSql, aTaskList[i]->sql());    
            if (dbsqlexec((DBPROCESS*)m_pMsSql) == FAIL)
            {
                m_oSqlLock.Unlock();
                return false;
            }
        }
    }
    m_oSqlLock.Unlock();

    return true;
}

bool wmMSSql::Query(const char *pSql, CDbResult*& pDbResult)
{
    pDbResult = NULL;
    if (NULL == m_pMsSql)
    {
        return false;
    }

    m_oSqlLock.Lock();

    dbcmd((DBPROCESS*)m_pMsSql, pSql);    
    if (dbsqlexec((DBPROCESS*)m_pMsSql) == FAIL)
    {
        //std::cout << "Query from database failed!" << std::endl;
        m_oSqlLock.Unlock();
        return false;
    }
    pDbResult = new wmMSSqlResult(m_pMsSql);

    m_oSqlLock.Unlock();

    
    return true;
}

bool wmMSSql::Query(CSqlTaskSet* const pTaskSet)
{
    std::vector<ISqlTask*>& aTaskList = *(pTaskSet->TaskList());

    if (pTaskSet->IsTransaction())
    {
        BeginTransaction();
        for (uint32 i=0; i<aTaskList.size(); ++i)
        {
            if (NULL == aTaskList[i])
            {
                continue;
            }
            if (!Query(aTaskList[i]->sql(), aTaskList[i]->GetResult()))
            {
                RollbackTransaction();
                pTaskSet->SetSucess(false);
                return false;
            }
        }
        CommitTransaction();
    }
    else
    {
        for (uint32 i=0; i<aTaskList.size(); ++i)
        {
            if (NULL == aTaskList[i])
            {
                continue;
            }
            if (!Query(aTaskList[i]->sql(), aTaskList[i]->GetResult()))
            {
                pTaskSet->SetSucess(false);
                return false;
            }
        }
    }
    pTaskSet->SetSucess(true);

    return true;
}

void wmMSSql::KeepAlive()
{

}

bool wmMSSql::BeginTransaction()
{
    return true;
}

bool wmMSSql::CommitTransaction()
{
    return true;
}

bool wmMSSql::RollbackTransaction()
{
    return true;
}

}
